package com.dhcc.utils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 辅助的辅助类
 * @author hibean@qq.com 2017年6月27日
 *
 */
public class UtilUtil {
	private static Logger LOG = LoggerFactory.getLogger(UtilUtil.class);	
	static Object[] put(Object arg0, Object[] args){
		Object[] result = new Object[args.length+1];
		result[0] = arg0;
		for (int i = 0; i < args.length; i++) {
			result[i+1] = args[i];
		}
		return result;
	}
	
	public static Map<String, String> scan(String... pkgs) {
		ClassScanner scanner = new ClassScanner();
		for (String pkg : pkgs) {
			scanner.scan(pkg);
		}
		List<String> strs = scanner.getClassNames();
		Map<String, String> result = new HashMap<String, String>(strs.size());
		for (String className : strs) {
			LOG.debug("scanned: {}", className);
			if(className.endsWith("Operator")){
				int idx = className.lastIndexOf('.');
				String op = className.substring(idx+1, className.length()-"Operator".length());
				char[] chars = op.toCharArray();
				chars[0] = Character.toLowerCase(chars[0]);
				op = new String(chars);
				LOG.info("map op: {} -> {} ", op, className);
				result.put(op, className);
			}
		}
		return new ConcurrentHashMap<String, String>(result);
	}

	@SuppressWarnings("unchecked")
	public static <T, TType> T op(Map<String, String> setting, Map<String, Operator<TType>> operators, String operator, TType first,
			Object[] args) {
		Operator<TType> instance = UtilUtil.<TType>getOperator(setting, operators, operator);
		return (T) instance.invoke(operator, first, args);
	}

	private static <TType> Operator<TType> getOperator(Map<String, String> setting, Map<String, Operator<TType>> operators, String operator) {
		if(operator==null){
			throw new OperatorException("operator 为 null");
		}
		if(operators.containsKey(operator)){
			return operators.get(operator);
		}
		Set<String> keys1 = operators.keySet();
		for (String key : keys1) {
			if(operator.startsWith(key)){
				Operator<TType> result = operators.get(key);
				put(operator, operators, result);
				return result;
			}
		}
		Set<String> keys = setting.keySet();
		for (String key : keys) {
			if(operator.startsWith(key)){
				String type = setting.get(key);
				Class<?> clazz;
				try {
					clazz = Class.forName(type);
					@SuppressWarnings("unchecked")
					Operator<TType> instance = (Operator<TType>) clazz.newInstance();
					put(key, operators, instance);
					put(operator, operators, instance);
					return instance;
				} catch (ClassNotFoundException e) {
					
				} catch (InstantiationException e) {
					
				} catch (IllegalAccessException e) {
					
				}
			}
		}
		throw new RuntimeException("operator:“"+operator+"” not support");
	}
	private static synchronized <TType> void put(String operator, Map<String, Operator<TType>> operators, Operator<TType> value){
		if(operator == null){
			throw new NullPointerException("operator is null");
		}
		operators.put(operator, value);
	}

	public static <T> void registry(String name,
			Class<? extends Operator<T>> clazz, Map<String, String> map) {
		if(name == null){
			throw new NullPointerException("name is null");
		}
		map.put(name, clazz.getName());
	}
}
